package moodish.dummy;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.LinkedList;

import moodish.comm.ClientComm;
import moodish.comm.ClientSideMessage;
import moodish.comm.ListenMessagesFromServer;
import moodish.comm.ServerSideMessage.Type;
import moodish.message.MessageFromClient;
import moodish.message.MessageFromServer;

/**
 * Class that implements the interface {@link #ClientComm}
 */
public class ClientCommDummy implements ClientComm {

	private final int PORT_NUMBER = 8010;
	private Socket clientSocket;
	private String nickname;
	private ObjectOutputStream toServer;
	private ObjectInputStream fromServer;
	private LinkedList<MessageFromServer> messageServer;

	@Override
	public void connect(String serverAddress, String nickname)
			throws UnknownHostException, IOException {
		clientSocket = new Socket(serverAddress, PORT_NUMBER);
		this.nickname = nickname;
		toServer = new ObjectOutputStream(clientSocket.getOutputStream());
		fromServer = new ObjectInputStream(clientSocket.getInputStream());
		messageServer = new LinkedList<MessageFromServer>();
		try {
			toServer.writeObject(new MessageFromClient(Type.CLIENT_CONNECTED,
					this.nickname, null));
			toServer.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (clientSocket != null && toServer != null && fromServer != null) {
			ListenMessagesFromServer listenConnections = new ListenMessagesFromServer(this);
			Thread clientThread = new Thread(listenConnections);
			clientThread.start();
		}

	}

	@Override
	public boolean isConnected() {
		return !clientSocket.isClosed();
	}

	@Override
	public void disconnect() {
		try {
			toServer.writeObject(new MessageFromClient(
					Type.CLIENT_DISCONNECTED, this.nickname, null));
			toServer.flush();
			clientSocket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public boolean hasNextMessage() {

		synchronized (messageServer)

		{
			if (messageServer.size() > 0) {
				return true;

			} else {
				return false;
			}
		}

	}

	@Override
	public ClientSideMessage getNextMessage() {

		synchronized (messageServer) {
			while (!hasNextMessage()) {

				try {
					messageServer.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return messageServer.poll();
		}
	}

	@Override
	public void sendMoodishMessage(String moodishMessage) {
		if (isConnected()) {
			try {

				toServer.writeObject(new MessageFromClient(
						Type.MOODISH_MESSAGE, this.nickname, moodishMessage));
				toServer.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	@Override
	public void friendship(String nickname) {
		if (isConnected()) {
			try {
				toServer.writeObject(new MessageFromClient(Type.FRIENDSHIP,
						this.nickname, nickname));
				toServer.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	@Override
	public void unfriendship(String nickname) {
		if (isConnected()) {
			try {
				toServer.writeObject(new MessageFromClient(Type.UNFRIENDSHIP,
						this.nickname, nickname));
				toServer.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * @return Returns the ObjectInputStream to read messages from the server
	 */
	public ObjectInputStream getFromServer()
	{
		return fromServer;
	}

	/**
	 * After a message received from the server, the client add the message to a LinkedList
	 * 
	 * @param message                 Message to add to the LinkedList
	 */
	public void addMessage(MessageFromServer message) {
		synchronized (messageServer) {
			messageServer.add(message);
			messageServer.notifyAll();
		}
	}
}